//
//  ControlFlowExample.swift
//  SwiftCode
//
//  Created by yuhus on 2023/6/27.
//

import Foundation

class ControlFlowExample: ListViewController {
  override func getItemCount() -> Int {
    data.count
  }
  
  override func getItem(_ indexPath: IndexPath) -> Item {
    data[indexPath.row]
  }
  
  private lazy var data: [Item] = [
    .init(title: "For-In", description: "stride 的使用", action: stride),
    .init(title: "Switch-区间匹配", description: "条件语句", action: { switchRange(2) }),
    .init(title: "Switch-元组匹配", description: "条件语句", action: { switchTuple((1, 1)) }),
    .init(title: "Switch-值绑定", description: "条件语句", action: { switchValueBindings((2, 0)) }),
    .init(title: "Switch-Where", description: "条件语句", action: { switchWhere((1, -1)) }),
    .init(title: "Switch-复合型 Cases", description: "条件语句", action: { switchCases((9, 0)) }),
    .init(title: "带标签的语句", description: "控制转移语句", action: snakesAndLadders),
  ]
}

private func stride() {
  print("stride(from:to:by:)")
  for tickMark in stride(from: 0, to: 60, by: 5) {
    // 每5分钟渲染一个刻度线（0, 5, 10, 15 ... 45, 50, 55）
    print("\(tickMark), ", terminator: "")
  }
  print("")
  
  print("stride(from:through:by:)")
  let hours = 12
  let hourInterval = 3
  for tickMark in stride(from: 3, through: hours, by: hourInterval) {
    // 每3小时渲染一个刻度线（3, 6, 9, 12）
    print("\(tickMark), ", terminator: "")
  }
  print("")
}

private func switchRange(_ number: Int) {
  switch number {
  case -1: print("-1")
  case 1...: print("大于 0", number)
  default: print("其他")
  }
}

private func switchTuple(_ somePoint: (Int, Int)) {
  switch somePoint {
  case (0, 0):
    print("\(somePoint) is at the origin")
  case (_, 0):
    print("\(somePoint) is on the x-axis")
  case (0, _):
    print("\(somePoint) is on the y-axis")
  case (-2...2, -2...2):
    print("\(somePoint) is inside the box")
  default:
    print("\(somePoint) is outside of the box")
  }
  // 输出“(1, 1) is inside the box”
}

private func switchValueBindings(_ anotherPoint: (Int, Int)) {
  switch anotherPoint {
  case (let x, 0):
    print("on the x-axis with an x value of \(x)")
  case (0, let y):
    print("on the y-axis with a y value of \(y)")
  case let (x, y):
    print("somewhere else at (\(x), \(y))")
  }
  // 输出“on the x-axis with an x value of 2”
}

/// 使用 `where` 语句来判断额外的条件
private func switchWhere(_ yetAnotherPoint: (Int, Int)) {
  switch yetAnotherPoint {
  case let (x, y) where x == y:
    print("(\(x), \(y)) is on the line x == y")
  case let (x, y) where x == -y:
    print("(\(x), \(y)) is on the line x == -y")
  case let (x, y):
    print("(\(x), \(y)) is just some arbitrary point")
  }
  // 输出“(1, -1) is on the line x == -y”
}

/// (let distance, 0) 匹配了在 x 轴上的值
/// (0, let distance) 匹配了在 y 轴上的值
private func switchCases(_ stillAnotherPoint: (Int, Int)) {
  switch stillAnotherPoint {
  case (let distance, 0), (0, let distance):
    print("On an axis, \(distance) from the origin")
  default:
    print("Not on an axis")
  }
  // 输出“On an axis, 9 from the origin”
}

/// [蛇和梯子（也叫做滑道和梯子）的小游戏](https://docs.swift.org/swift-book/images/snakesAndLadders@2x.png)
///
/// 游戏的规则如下：
/// - 游戏盘面包括 25 个方格，游戏目标是达到（超过重新投掷🎲）第 25 个方格；
/// - 每一轮，你通过掷一个六面体骰子来确定你移动方块的步数，移动的路线由上图中横向的虚线所示；
/// - 如果在某轮结束，你移动到了梯子的底部，可以顺着梯子爬上去；
/// - 如果在某轮结束，你移动到了蛇的头部，你会顺着蛇的身体滑下去。
private func snakesAndLadders() {
  let finalSquare = 25
  var board = [Int](repeating: 0, count: finalSquare + 1)
  board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
  board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
  var square = 0
  var diceRoll = 0
  
gameLoop: while square != finalSquare {
  diceRoll += 1
  if diceRoll == 7 { diceRoll = 1 }
  switch square + diceRoll {
  case finalSquare:
    // 骰子数刚好使玩家移动到最终的方格里，游戏结束。
    break gameLoop
  case let newSquare where newSquare > finalSquare:
    // 骰子数将会使玩家的移动超出最后的方格，那么这种移动是不合法的，玩家需要重新掷骰子
    continue gameLoop
  default:
    // 合法移动，做正常的处理
    square += diceRoll
    square += board[square]
  }
  print("Roll \(diceRoll), Square [\(square)]")
}
  print("Roll \(diceRoll), Game over!")
}
